/*
	This file is part of SRServerLibrary.
	Foobar is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	
	SRServerLibrary is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with SRServerLibrary.  If not, see <http://www.gnu.org/licenses/>.
*/



/*
	This is a quick and dirty SupeRemote client(remote control) simulator. It acts as a client. A number of commands is sent and the response is compared with the expected response. Test results are printed to stdout.

	TODO:
		Free memory
		Use string comparison function
*/




#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <CUnit/Basic.h>
#include <CUnit/CUnit.h>

#define PORT "4567"

#define MAXDATASIZE 100


int sockfd, numbytes;  
char buf[MAXDATASIZE];
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
char *hostaddress;
int argcount;

// testing statistics
int testcount = 0;
int successcount = 0;


int emConnect();
char* emTestSend(char*);
char* emSend(char*);
char* emGet();
void runTests();

int init_suite();
int clean_suite();




// get sockaddr, IPv4 or IPv6
void *get_in_addr(struct sockaddr *sa)
{
	if (sa->sa_family == AF_INET) {
		return &(((struct sockaddr_in*)sa)->sin_addr);
	}

	return &(((struct sockaddr_in6*)sa)->sin6_addr);
}


int main(int argc, char *argv[])
{
	argcount = argc;
	hostaddress = argv[1];
	
	if(argc!=2)
	{
		printf("Bad argument count. Expecting host name as parameter.\n");
		return 1;
	}
	
	// set up CUnit
	
	CU_pSuite pSuite = NULL;

	/* initialize the CUnit test registry */
	if (CUE_SUCCESS != CU_initialize_registry())
	{
		return CU_get_error();
	}

	/* add a suite to the registry */
	pSuite = CU_add_suite("SRServer response test suite", init_suite, clean_suite);
	if (NULL == pSuite) {
		CU_cleanup_registry();
		return CU_get_error();
	}
	
	if (NULL == CU_add_test(pSuite, "testing by sending commands to server and validating the response", runTests))
	{
		CU_cleanup_registry();
		return CU_get_error();
	}
	
	/* Run all tests using the CUnit Basic interface */
	CU_basic_set_mode(CU_BRM_VERBOSE);
	CU_basic_run_tests();
	CU_cleanup_registry();
	return CU_get_error();
	

	return 0;
}


char* emTestSend(char *sendstr)
{
	char *response;
	
	emConnect();
	emSend(sendstr);
	response = emGet();
	close(sockfd);
	
	sleep(1);
	
	return response;
}


char* emSend(char *message)
{
	send(sockfd, message, strlen(message), 0);
}


char* emGet()
{
	if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
	    perror("recv");
	    exit(1);
	}

	buf[numbytes] = '\0';
	
	return buf;
}


int emConnect()
{
	memset(&hints, 0, sizeof hints);
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	if ((rv = getaddrinfo(hostaddress, PORT, &hints, &servinfo)) != 0) {
		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
		return 1;
	}

	// loop through all the results and connect to the first we can
	for(p = servinfo; p != NULL; p = p->ai_next) {
		if ((sockfd = socket(p->ai_family, p->ai_socktype,
				p->ai_protocol)) == -1) {
			perror("client: socket");
			continue;
		}

		if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
			close(sockfd);
			perror("client: connect");
			continue;
		}

		break;
	}

	if (p == NULL) {
		fprintf(stderr, "client: failed to connect\n");
		return 2;
	}

	inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
			s, sizeof s);
	//printf("client: connecting to %s\n", s);

	freeaddrinfo(servinfo); // all done with this structure
}


int init_suite()
{
	return 0;
}


int clean_suite()
{
	return 0;
}


void runTests()
{
	CU_ASSERT(emTestSend("getr_play") == "played");
	CU_ASSERT(emTestSend("getr_pause") == "paused");
}

